import datetime
import sys
import os
# 获取当前文件所在目录的父目录（即项目根目录）
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if project_root not in sys.path:
    sys.path.append(project_root)

import execjs
import requests
import yaml
import time
import random
from douyin.abogus import ABogus as AB
from douyin.xbogus import XBogus as XB
from urllib.parse import urlencode, quote
from pydantic import BaseModel, Field


class BogusManager:
    @classmethod
    def ab_model_2_endpoint(cls, params: dict, user_agent: str) -> str:
        if not isinstance(params, dict):
            raise TypeError("参数必须是字典类型")

        try:
            ab_value = AB().get_value(params, )
        except Exception as e:
            print("生成A-Bogus失败: {0})".format(e))
        a_bogus = quote(ab_value, safe='')
        return a_bogus
    # 字典方法生成X-Bogus参数
    @classmethod
    def xb_model_2_endpoint(cls, base_endpoint: str, params: dict, user_agent: str) -> str:
        if not isinstance(params, dict):
            raise TypeError("参数必须是字典类型")

        param_str = "&".join([f"{k}={v}" for k, v in params.items()])

        try:
            xb_value = XB(user_agent).getXBogus(param_str)
        except Exception as e:
            print("生成X-Bogus失败: {0})".format(e))

        # 检查base_endpoint是否已有查询参数 (Check if base_endpoint already has query parameters)
        separator = "&" if "?" in base_endpoint else "?"

        final_endpoint = f"{base_endpoint}{separator}{param_str}&X-Bogus={xb_value[1]}"

        return final_endpoint


douyin_sign_obj = execjs.compile(open('static/douyin.js', encoding='utf-8-sig').read())

def get_a_bogus_from_js(params: str, user_agent: str):
    """
    通过js获取 a_bogus 参数
    Args:
        url:
        params:
        user_agent:

    Returns:

    """
    sign_js_name = "sign_datail"

    return douyin_sign_obj.call(sign_js_name, params, user_agent)

def gen_a_bogus(params: dict, user_agent: str) -> str:
    ab = AB()
    if not isinstance(params, dict):
        raise TypeError("参数必须是字典类型")

    try:
        ab_value = ab.get_value(params, )
    except Exception as e:
        print("生成A-Bogus失败: {0})".format(e))
    a_bogus = quote(ab_value, safe='')
    return a_bogus    

class BaseRequestModel(BaseModel):
    aid: str = "6383"
    channel: str = "channel_pc_web"
    pc_client_type: int = 1
    version_code: str = "190500"
    version_name: str = "19.5.0"
    cookie_enabled: str = "true"
    screen_width: int = 1920
    screen_height: int = 1080
    browser_language: str = "zh-CN"
    browser_platform: str = "Win32"
    browser_name: str = "Chrome"
    browser_version: str = "130.0.0.0"
    browser_online: str = "true"
    engine_name: str = "Blink"
    engine_version: str = "130.0.0.0"
    os_name: str = "Windows"
    os_version: str = "10"
    cpu_core_num: int = 12
    device_memory: int = 8
    platform: str = "PC"
    downlink: str = "10"
    effective_type: str = "4g"
    from_user_page: str = "1"
    locate_query: str = "false"
    need_time_list: str = "1"
    pc_libra_divert: str = "Windows"
    publish_video_strategy_type: str = "2"
    round_trip_time: str = "0"
    show_live_replay_strategy: str = "1"
    time_list_query: str = "0"
    whale_cut_token: str = ""
    update_version_code: str = "170400"
    webid : str = "7490893657928926735"



class PostDetail(BaseRequestModel):
    aweme_id: str



def get_timestamp(unit: str = "milli"):
    """
    根据给定的单位获取当前时间 (Get the current time based on the given unit)

    Args:
        unit (str): 时间单位，可以是 "milli"、"sec"、"min" 等
            (The time unit, which can be "milli", "sec", "min", etc.)

    Returns:
        int: 根据给定单位的当前时间 (The current time based on the given unit)
    """

    now = datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)
    if unit == "milli":
        return int(now.total_seconds() * 1000)
    elif unit == "sec":
        return int(now.total_seconds())
    elif unit == "min":
        return int(now.total_seconds() / 60)
    else:
        raise ValueError("Unsupported time unit")


def gen_verify_fp() -> str:
    """
    生成verifyFp 与 s_v_web_id (Generate verifyFp)
    """
    base_str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    t = len(base_str)
    milliseconds = int(round(time.time() * 1000))
    base36 = ""
    while milliseconds > 0:
        remainder = milliseconds % 36
        if remainder < 10:
            base36 = str(remainder) + base36
        else:
            base36 = chr(ord("a") + remainder - 10) + base36
        milliseconds = int(milliseconds / 36)
    r = base36
    o = [""] * 36
    o[8] = o[13] = o[18] = o[23] = "_"
    o[14] = "4"

    for i in range(36):
        if not o[i]:
            n = 0 or int(random.random() * t)
            if i == 19:
                n = 3 & n | 8
            o[i] = base_str[n]

    return "verify_" + r + "_" + "".join(o)

def gen_s_v_web_id() -> str:
    return gen_verify_fp()

with open(f"./douyin/douyin_config.yaml", "r", encoding="utf-8") as f:
    config = yaml.safe_load(f)
def get_douyin_headers():
    douyin_config = config["TokenManager"]["douyin"]
    kwargs = {
        "headers": {
            "Accept-Language": douyin_config["headers"]["Accept-Language"],
            "User-Agent": douyin_config["headers"]["User-Agent"],
            "Referer": douyin_config["headers"]["Referer"],
            "Cookie": douyin_config["headers"]["Cookie"],
        },
        "proxies": {"http://": douyin_config["proxies"]["http"], "https://": douyin_config["proxies"]["https"]},
    }
    return kwargs
